home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / aplictns / dkbtrace / part07 < prev    next >
Encoding:
Internet Message Format  |  1990-09-03  |  42.0 KB

  1. Path: abcfd20.larc.nasa.gov!amiga-request
  2. From: amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
  3. Subject: v90i255: DKBTrace 2.01 - DKBtrace Ray-Tracer, Part07/10
  4. Reply-To: David Schanen <mtv@milton.u.washington.edu>
  5. Newsgroups: comp.sources.amiga
  6. Message-ID: <comp.sources.amiga:v90i255@abcfd20.larc.nasa.gov>
  7. References: <comp.sources.amiga:v90i249@abcfd20.larc.nasa.gov>
  8. Date: 03 Sep 90 23:22:24 GMT
  9. Approved: tadguy@uunet.UU.NET (Tad Guy)
  10. X-Mail-Submissions-To: amiga@uunet.uu.net
  11. X-Post-Discussions-To: comp.sys.amiga
  12.  
  13. Submitted-by: David Schanen <mtv@milton.u.washington.edu>
  14. Posting-number: Volume 90, Issue 255
  15. Archive-name: applications/dkbtrace-2.01/part07
  16.  
  17. #!/bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 7 (of 10)."
  24. # Contents:  src/iff.h src/lighting.c
  25. # Wrapped by tadguy@abcfd20 on Mon Sep  3 19:21:21 1990
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'src/iff.h' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'src/iff.h'\"
  29. else
  30. echo shar: Extracting \"'src/iff.h'\" \(20481 characters\)
  31. sed "s/^X//" >'src/iff.h' <<'END_OF_FILE'
  32. X#ifndef IFF_H
  33. X#define IFF_H
  34. X/*----------------------------------------------------------------------*/
  35. X/* IFF.H  defs for IFF-85 Interchange Format Files.            1/22/86 */
  36. X/*                                    */
  37. X/* By Jerry Morrison and Steve Shaw, Electronic Arts.            */
  38. X/* This software is in the public domain.                */
  39. X/*----------------------------------------------------------------------*/
  40. X
  41. X#ifndef COMPILER_H
  42. X#include "iff/compiler.h"
  43. X#endif
  44. X
  45. X#ifndef LIBRARIES_DOS_H
  46. X#include "libraries/dos.h"
  47. X#endif
  48. X
  49. X#ifndef OFFSET_BEGINNING
  50. X#define OFFSET_BEGINNING OFFSET_BEGINING
  51. X#endif
  52. X
  53. Xtypedef LONG IFFP;    /* Status code result from an IFF procedure */
  54. X    /* LONG, because must be type compatable with ID for GetChunkHdr.*/
  55. X    /* Note that the error codes below are not legal IDs.*/
  56. X#define IFF_OKAY   0L    /* Keep going...*/
  57. X#define END_MARK  -1L    /* As if there was a chunk at end of group.*/
  58. X#define IFF_DONE  -2L    /* clientProc returns this when it has READ enough.
  59. X             * It means return thru all levels. File is Okay.*/
  60. X#define DOS_ERROR -3L
  61. X#define NOT_IFF   -4L    /* not an IFF file.*/
  62. X#define NO_FILE   -5L    /* Tried to open file, DOS didn't find it.*/
  63. X#define CLIENT_ERROR -6L /* Client made invalid request, for instance, write
  64. X             * a negative size chunk.*/
  65. X#define BAD_FORM  -7L    /* A client read proc complains about FORM semantics;
  66. X             * e.g. valid IFF, but missing a required chunk.*/
  67. X#define SHORT_CHUNK -8L    /* Client asked to IFFReadBytes more bytes than left
  68. X             * in the chunk. Could be client bug or bad form.*/
  69. X#define BAD_IFF   -9L    /* mal-formed IFF file. [TBD] Expand this into a
  70. X             * range of error codes.*/
  71. X#define LAST_ERROR BAD_IFF
  72. X
  73. X/* This MACRO is used to RETURN immediately when a termination condition is
  74. X * found. This is a pretty weird macro. It requires the caller to declare a
  75. X * local "IFFP iffp" and assign it. This wouldn't work as a subroutine since
  76. X * it returns for it's caller. */
  77. X#define CheckIFFP()   { if (iffp != IFF_OKAY) return(iffp); }
  78. X
  79. X
  80. X/* ---------- ID -------------------------------------------------------*/
  81. X
  82. Xtypedef LONG ID;    /* An ID is four printable ASCII chars but
  83. X             * stored as a LONG for efficient copy & compare.*/
  84. X
  85. X/* Four-character IDentifier builder.*/
  86. X#define MakeID(a,b,c,d)  ( (LONG)(a)<<24L | (LONG)(b)<<16L | (c)<<8 | (d) )
  87. X
  88. X/* Standard group IDs.  A chunk with one of these IDs contains a
  89. X   SubTypeID followed by zero or more chunks.*/
  90. X#define FORM MakeID('F','O','R','M')
  91. X#define PROP MakeID('P','R','O','P')
  92. X#define LIST MakeID('L','I','S','T')
  93. X#define CAT  MakeID('C','A','T',' ')
  94. X#define FILLER MakeID(' ',' ',' ',' ')
  95. X/* The IDs "FOR1".."FOR9", "LIS1".."LIS9", & "CAT1".."CAT9" are reserved
  96. X * for future standardization.*/
  97. X
  98. X/* Pseudo-ID used internally by chunk reader and writer.*/
  99. X#define NULL_CHUNK 0L           /* No current chunk.*/
  100. X
  101. X
  102. X/* ---------- Chunk ----------------------------------------------------*/
  103. X
  104. X/* All chunks start with a type ID and a count of the data bytes that 
  105. X   follow--the chunk's "logicl size" or "data size". If that number is odd,
  106. X   a 0 pad byte is written, too. */
  107. Xtypedef struct {
  108. X    ID      ckID;
  109. X    LONG  ckSize;
  110. X    } ChunkHeader;
  111. X
  112. Xtypedef struct {
  113. X    ID      ckID;
  114. X    LONG  ckSize;
  115. X    UBYTE ckData[ 1 /*REALLY: ckSize*/ ];
  116. X    } Chunk;
  117. X
  118. X/* Pass ckSize = szNotYetKnown to the writer to mean "compute the size".*/
  119. X#define szNotYetKnown 0x80000001L
  120. X
  121. X/* Need to know whether a value is odd so can word-align.*/
  122. X#define IS_ODD(a)   ((a) & 1)
  123. X
  124. X/* This macro rounds up to an even number. */
  125. X#define WordAlign(size)   ((size+1)&~1)
  126. X
  127. X/* ALL CHUNKS MUST BE PADDED TO EVEN NUMBER OF BYTES.
  128. X * ChunkPSize computes the total "physical size" of a padded chunk from
  129. X * its "data size" or "logical size". */
  130. X#define ChunkPSize(dataSize)  (WordAlign(dataSize) + sizeof(ChunkHeader))
  131. X
  132. X/* The Grouping chunks (LIST, FORM, PROP, & CAT) contain concatenations of
  133. X * chunks after a subtype ID that identifies the content chunks.
  134. X * "FORM type XXXX", "LIST of FORM type XXXX", "PROPerties associated
  135. X * with FORM type XXXX", or "conCATenation of XXXX".*/
  136. Xtypedef struct {
  137. X    ID      ckID;
  138. X    LONG  ckSize;    /* this ckSize includes "grpSubID".*/
  139. X    ID    grpSubID;
  140. X    } GroupHeader;
  141. X
  142. Xtypedef struct {
  143. X    ID      ckID;
  144. X    LONG  ckSize;
  145. X    ID    grpSubID;
  146. X    UBYTE grpData[ 1 /*REALLY: ckSize-sizeof(grpSubID)*/ ];
  147. X    } GroupChunk;
  148. X
  149. X
  150. X/* ---------- IFF Reader -----------------------------------------------*/
  151. X
  152. X/******** Routines to support a stream-oriented IFF file reader *******
  153. X *
  154. X * These routines handle lots of details like error checking and skipping
  155. X * over padding. They're also careful not to read past any containing context.
  156. X *
  157. X * These routines ASSUME they're the only ones reading from the file.
  158. X * Client should check IFFP error codes. Don't press on after an error!
  159. X * These routines try to have no side effects in the error case, except
  160. X * partial I/O is sometimes unavoidable.
  161. X *
  162. X * All of these routines may return DOS_ERROR. In that case, ask DOS for the
  163. X * specific error code.
  164. X *
  165. X * The overall scheme for the low level chunk reader is to open a "group read
  166. X * context" with OpenRIFF or OpenRGroup, read the chunks with GetChunkHdr
  167. X * (and its kin) and IFFReadBytes, and close the context with CloseRGroup.
  168. X *
  169. X * The overall scheme for reading an IFF file is to use ReadIFF, ReadIList,
  170. X * and ReadICat to scan the file. See those procedures, ClientProc (below),
  171. X * and the skeleton IFF reader. */
  172. X
  173. X/* Client passes ptrs to procedures of this type to ReadIFF which call them
  174. X * back to handle LISTs, FORMs, CATs, and PROPs.
  175. X *
  176. X * Use the GroupContext ptr when calling reader routines like GetChunkHdr.
  177. X * Look inside the GroupContext ptr for your ClientFrame ptr. You'll
  178. X * want to type cast it into a ptr to your containing struct to get your
  179. X * private contextual data (stacked property settings). See below. */
  180. X#ifdef FDwAT
  181. Xtypedef IFFP ClientProc(struct _GroupContext *);
  182. X#else
  183. Xtypedef IFFP ClientProc();
  184. X#endif
  185. X
  186. X/* Client's context for reading an IFF file or a group.
  187. X * Client should actually make this the first component of a larger struct
  188. X * (it's personal stack "frame") that has a field to store each "interesting"
  189. X * property encountered.
  190. X * Either initialize each such field to a global default or keep a boolean
  191. X * indicating if you've read a property chunk into that field.
  192. X * Your getList and getForm procs should allocate a new "frame" and copy the
  193. X * parent frame's contents. The getProp procedure should store into the frame
  194. X * allocated by getList for the containing LIST. */
  195. Xtypedef struct _ClientFrame {
  196. X   ClientProc *getList, *getProp, *getForm, *getCat;
  197. X    /* client's own data follows; place to stack property settings */
  198. X    } ClientFrame;
  199. X
  200. X/* Our context for reading a group chunk. */
  201. Xtypedef struct _GroupContext {
  202. X    struct _GroupContext *parent; /* Containing group; NULL => whole file. */
  203. X    ClientFrame *clientFrame;     /* Reader data & client's context state. */
  204. X    BPTR file;        /* Byte-stream file handle. */
  205. X    LONG position;    /* The context's logical file position. */
  206. X    LONG bound;        /* File-absolute context bound
  207. X             * or szNotYetKnown (writer only). */
  208. X    ChunkHeader ckHdr;    /* Current chunk header. ckHdr.ckSize = szNotYetKnown
  209. X             * means we need to go back and set the size (writer only).
  210. X             * See also Pseudo-IDs, above. */
  211. X    ID subtype;        /* Group's subtype ID when reading. */
  212. X    LONG bytesSoFar;    /* # bytes read/written of current chunk's data. */
  213. X    } GroupContext;
  214. X
  215. X/* Computes the number of bytes not yet read from the current chunk, given
  216. X * a group read context gc. */
  217. X#define ChunkMoreBytes(gc)  ((gc)->ckHdr.ckSize - (gc)->bytesSoFar)
  218. X
  219. X
  220. X/***** Low Level IFF Chunk Reader *****/
  221. X
  222. X#ifdef FDwAT
  223. X
  224. X/* Given an open file, open a read context spanning the whole file.
  225. X * This is normally only called by ReadIFF.
  226. X * This sets new->clientFrame = clientFrame.
  227. X * ASSUME context allocated by caller but not initialized.
  228. X * ASSUME caller doesn't deallocate the context before calling CloseRGroup.
  229. X * NOT_IFF ERROR if the file is too short for even a chunk header.*/
  230. Xextern IFFP OpenRIFF(BPTR, GroupContext *, ClientFrame *);
  231. X             /*  file, new,            clientFrame  */
  232. X
  233. X/* Open the remainder of the current chunk as a group read context.
  234. X * This will be called just after the group's subtype ID has been read
  235. X * (automatically by GetChunkHdr for LIST, FORM, PROP, and CAT) so the
  236. X * remainder is a sequence of chunks.
  237. X * This sets new->clientFrame = parent->clientFrame. The caller should repoint
  238. X * it at a new clientFrame if opening a LIST context so it'll have a "stack
  239. X * frame" to store PROPs for the LIST. (It's usually convenient to also
  240. X * allocate a new Frame when you encounter FORM of the right type.)
  241. X *
  242. X * ASSUME new context allocated by caller but not initialized.
  243. X * ASSUME caller doesn't deallocate the context or access the parent context
  244. X * before calling CloseRGroup.
  245. X * BAD_IFF ERROR if context end is odd or extends past parent. */
  246. Xextern IFFP OpenRGroup(GroupContext *, GroupContext *);
  247. X           /*  parent,         new  */
  248. X
  249. X/* Close a group read context, updating its parent context.
  250. X * After calling this, the old context may be deallocated and the parent
  251. X * context can be accessed again. It's okay to call this particular procedure
  252. X * after an error has occurred reading the group.
  253. X * This always returns IFF_OKAY. */
  254. Xextern IFFP CloseRGroup(GroupContext *);
  255. X            /*  old  */
  256. X
  257. X/* Skip any remaining bytes of the previous chunk and any padding, then
  258. X * read the next chunk header into context.ckHdr.
  259. X * If the ckID is LIST, FORM, CAT, or PROP, this automatically reads the
  260. X * subtype ID into context->subtype.
  261. X * Caller should dispatch on ckID (and subtype) to an appropriate handler.
  262. X *
  263. X * RETURNS context.ckHdr.ckID (the ID of the new chunk header); END_MARK
  264. X * if there are no more chunks in this context; or NOT_IFF if the top level
  265. X * file chunk isn't a FORM, LIST, or CAT; or BAD_IFF if malformed chunk, e.g.
  266. X * ckSize is negative or too big for containing context, ckID isn't positive,
  267. X * or we hit end-of-file.
  268. X *
  269. X * See also GetFChunkHdr, GetF1ChunkHdr, and GetPChunkHdr, below.*/
  270. Xextern ID       GetChunkHdr(GroupContext *);
  271. X  /*  context.ckHdr.ckID    context  */
  272. X
  273. X/* Read nBytes number of data bytes of current chunk. (Use OpenGroup, etc.
  274. X * instead to read the contents of a group chunk.) You can call this several
  275. X * times to read the data piecemeal.
  276. X * CLIENT_ERROR if nBytes < 0. SHORT_CHUNK if nBytes > ChunkMoreBytes(context)
  277. X * which could be due to a client bug or a chunk that's shorter than it
  278. X * ought to be (bad form). (on either CLIENT_ERROR or SHORT_CHUNK,
  279. X * IFFReadBytes won't read any bytes.) */
  280. Xextern IFFP IFFReadBytes(GroupContext *, BYTE *, LONG);
  281. X             /*  context,        buffer, nBytes  */
  282. X
  283. X
  284. X/***** IFF File Reader *****/
  285. X
  286. X/* This is a noop ClientProc that you can use for a getList, getForm, getProp,
  287. X * or getCat procedure that just skips the group. A simple reader might just
  288. X * implement getForm, store ReadICat in the getCat field of clientFrame, and
  289. X * use SkipGroup for the getList and getProp procs.*/
  290. Xextern IFFP SkipGroup(GroupContext *);
  291. X
  292. X/* IFF file reader.
  293. X * Given an open file, allocate a group context and use it to read the FORM,
  294. X * LIST, or CAT and it's contents. The idea is to parse the file's contents,
  295. X * and for each FORM, LIST, CAT, or PROP encountered, call the getForm,
  296. X * getList, getCat, or getProp procedure in clientFrame, passing the
  297. X * GroupContext ptr.
  298. X * This is achieved with the aid of ReadIList (which your getList should
  299. X * call) and ReadICat (which your getCat should call, if you don't just use
  300. X * ReadICat for your getCat). If you want to handle FORMs, LISTs, and CATs
  301. X * nested within FORMs, the getForm procedure must dispatch to getForm,
  302. X * getList, and getCat (it can use GetF1ChunkHdr to make this easy).
  303. X *
  304. X * Normal return is IFF_OKAY (if whole file scanned) or IFF_DONE (if a client
  305. X * proc said "done" first).
  306. X * See the skeletal getList, getForm, getCat, and getProp procedures. */
  307. Xextern IFFP ReadIFF(BPTR, ClientFrame *);
  308. X                /*  file, clientFrame  */
  309. X
  310. X/* IFF LIST reader.
  311. X * Your "getList" procedure should allocate a ClientFrame, copy the parent's
  312. X * ClientFrame, and then call this procedure to do all the work.
  313. X *
  314. X * Normal return is IFF_OKAY (if whole LIST scanned) or IFF_DONE (if a client
  315. X * proc said "done" first).
  316. X * BAD_IFF ERROR if a PROP appears after a non-PROP. */
  317. Xextern IFFP ReadIList(GroupContext *, ClientFrame *);
  318. X          /*  parent,         clientFrame  */
  319. X
  320. X/* IFF CAT reader.
  321. X * Most clients can simply use this to read their CATs. If you must do extra
  322. X * setup work, put a ptr to your getCat procedure in the clientFrame, and
  323. X * have that procedure call ReadICat to do the detail work.
  324. X *
  325. X * Normal return is IFF_OKAY (if whole CAT scanned) or IFF_DONE (if a client
  326. X * proc said "done" first).
  327. X * BAD_IFF ERROR if a PROP appears in the CAT. */
  328. Xextern IFFP ReadICat(GroupContext *);
  329. X         /*  parent  */
  330. X
  331. X/* Call GetFChunkHdr instead of GetChunkHdr to read each chunk inside a FORM.
  332. X * It just calls GetChunkHdr and returns BAD_IFF if it gets a PROP chunk. */
  333. Xextern ID    GetFChunkHdr(GroupContext *);
  334. X  /*  context.ckHdr.ckID    context  */
  335. X
  336. X/* GetF1ChunkHdr is like GetFChunkHdr, but it automatically dispatches to the
  337. X * getForm, getList, and getCat procedure (and returns the result) if it
  338. X * encounters a FORM, LIST, or CAT. */
  339. Xextern ID    GetF1ChunkHdr(GroupContext *);
  340. X  /*  context.ckHdr.ckID    context  */
  341. X
  342. X/* Call GetPChunkHdr instead of GetChunkHdr to read each chunk inside a PROP.
  343. X * It just calls GetChunkHdr and returns BAD_IFF if it gets a group chunk. */
  344. Xextern ID    GetPChunkHdr(GroupContext *);
  345. X  /*  context.ckHdr.ckID    context  */
  346. X
  347. X#else /* not FDwAT */
  348. X
  349. Xextern IFFP OpenRIFF();
  350. Xextern IFFP OpenRGroup();
  351. Xextern IFFP CloseRGroup();
  352. Xextern ID   GetChunkHdr();
  353. Xextern IFFP IFFReadBytes();
  354. Xextern IFFP SkipGroup();
  355. Xextern IFFP ReadIFF();
  356. Xextern IFFP ReadIList();
  357. Xextern IFFP ReadICat();
  358. Xextern ID   GetFChunkHdr();
  359. Xextern ID   GetF1ChunkHdr();
  360. Xextern ID   GetPChunkHdr();
  361. X
  362. X#endif /* not FDwAT */
  363. X
  364. X/* ---------- IFF Writer -----------------------------------------------*/
  365. X
  366. X/******* Routines to support a stream-oriented IFF file writer *******
  367. X *
  368. X * These routines will random access back to set a chunk size value when the
  369. X * caller doesn't know it ahead of time. They'll also do things automatically
  370. X * like padding and error checking.
  371. X *
  372. X * These routines ASSUME they're the only ones writing to the file.
  373. X * Client should check IFFP error codes. Don't press on after an error!
  374. X * These routines try to have no side effects in the error case, except that
  375. X * partial I/O is sometimes unavoidable.
  376. X *
  377. X * All of these routines may return DOS_ERROR. In that case, ask DOS for the
  378. X * specific error code.
  379. X *
  380. X * The overall scheme is to open an output GroupContext via OpenWIFF or
  381. X * OpenWGroup, call either PutCk or {PutCkHdr {IFFWriteBytes}* PutCkEnd} for
  382. X * each chunk, then use CloseWGroup to close the GroupContext.
  383. X *
  384. X * To write a group (LIST, FORM, PROP, or CAT), call StartWGroup, write out
  385. X * its chunks, then call EndWGroup. StartWGroup automatically writes the
  386. X * group header and opens a nested context for writing the contents.
  387. X * EndWGroup closes the nested context and completes the group chunk. */
  388. X
  389. X
  390. X#ifdef FDwAT
  391. X
  392. X/* Given a file open for output, open a write context.
  393. X * The "limit" arg imposes a fence or upper limit on the logical file
  394. X * position for writing data in this context. Pass in szNotYetKnown to be
  395. X * bounded only by disk capacity.
  396. X * ASSUME new context structure allocated by caller but not initialized.
  397. X * ASSUME caller doesn't deallocate the context before calling CloseWGroup.
  398. X * The caller is only allowed to write out one FORM, LIST, or CAT in this top
  399. X * level context (see StartWGroup and PutCkHdr).
  400. X * CLIENT_ERROR if limit is odd.*/
  401. Xextern IFFP OpenWIFF(BPTR, GroupContext *, LONG);
  402. X         /*  file, new,            limit {file position}  */
  403. X
  404. X/* Start writing a group (presumably LIST, FORM, PROP, or CAT), opening a
  405. X * nested context. The groupSize includes all nested chunks + the subtype ID.
  406. X *
  407. X * The subtype of a LIST or CAT is a hint at the contents' FORM type(s). Pass
  408. X * in FILLER if it's a mixture of different kinds.
  409. X *
  410. X * This writes the chunk header via PutCkHdr, writes the subtype ID via
  411. X * IFFWriteBytes, and calls OpenWGroup. The caller may then write the nested
  412. X * chunks and finish by calling EndWGroup.
  413. X * The OpenWGroup call sets new->clientFrame = parent->clientFrame.
  414. X *
  415. X * ASSUME new context structure allocated by caller but not initialized.
  416. X * ASSUME caller doesn't deallocate the context or access the parent context
  417. X * before calling CloseWGroup.
  418. X * ERROR conditions: See PutCkHdr, IFFWriteBytes, OpenWGroup. */
  419. Xextern IFFP StartWGroup(GroupContext *, ID, LONG, ID, GroupContext *);
  420. X            /*  parent, groupType, groupSize, subtype, new  */
  421. X
  422. X/* End a group started by StartWGroup.
  423. X * This just calls CloseWGroup and PutCkEnd.
  424. X * ERROR conditions: See CloseWGroup and PutCkEnd. */
  425. Xextern IFFP EndWGroup(GroupContext *);
  426. X            /*  old  */
  427. X
  428. X/* Open the remainder of the current chunk as a group write context.
  429. X * This is normally only called by StartWGroup.
  430. X *
  431. X * Any fixed limit to this group chunk or a containing context will impose
  432. X * a limit on the new context.
  433. X * This will be called just after the group's subtype ID has been written
  434. X * so the remaining contents will be a sequence of chunks.
  435. X * This sets new->clientFrame = parent->clientFrame.
  436. X * ASSUME new context structure allocated by caller but not initialized.
  437. X * ASSUME caller doesn't deallocate the context or access the parent context
  438. X * before calling CloseWGroup.
  439. X * CLIENT_ERROR if context end is odd or PutCkHdr wasn't called first. */
  440. Xextern IFFP OpenWGroup(GroupContext *, GroupContext *);
  441. X           /*  parent,         new  */
  442. X
  443. X/* Close a write context and update its parent context.
  444. X * This is normally only called by EndWGroup.
  445. X *
  446. X * If this is a top level context (created by OpenWIFF) we'll set the file's
  447. X * EOF (end of file) but won't close the file.
  448. X * After calling this, the old context may be deallocated and the parent
  449. X * context can be accessed again.
  450. X *
  451. X * Amiga DOS Note: There's no call to set the EOF. We just position to the
  452. X * desired end and return. Caller must Close file at that position.
  453. X * CLIENT_ERROR if PutCkEnd wasn't called first. */
  454. Xextern IFFP CloseWGroup(GroupContext *);
  455. X            /*  old  */
  456. X
  457. X/* Write a whole chunk to a GroupContext. This writes a chunk header, ckSize
  458. X * data bytes, and (if needed) a pad byte. It also updates the GroupContext.
  459. X * CLIENT_ERROR if ckSize == szNotYetKnown. See also PutCkHdr errors. */
  460. Xextern IFFP PutCk(GroupContext *, ID,   LONG,   BYTE *);
  461. X          /*  context,        ckID, ckSize, *data  */
  462. X
  463. X/* Write just a chunk header. Follow this will any number of calls to
  464. X * IFFWriteBytes and finish with PutCkEnd.
  465. X * If you don't yet know how big the chunk is, pass in ckSize = szNotYetKnown,
  466. X * then PutCkEnd will set the ckSize for you later.
  467. X * Otherwise, IFFWriteBytes and PutCkEnd will ensure that the specified
  468. X * number of bytes get written.
  469. X * CLIENT_ERROR if the chunk would overflow the GroupContext's bound, if
  470. X * PutCkHdr was previously called without a matching PutCkEnd, if ckSize < 0
  471. X * (except szNotYetKnown), if you're trying to write something other
  472. X * than one FORM, LIST, or CAT in a top level (file level) context, or
  473. X * if ckID <= 0 (these illegal ID values are used for error codes). */
  474. Xextern IFFP PutCkHdr(GroupContext *, ID,   LONG);
  475. X         /*  context,        ckID, ckSize  */
  476. X
  477. X/* Write nBytes number of data bytes for the current chunk and update
  478. X * GroupContext.
  479. X * CLIENT_ERROR if this would overflow the GroupContext's limit or the
  480. X * current chunk's ckSize, or if PutCkHdr wasn't called first, or if
  481. X * nBytes < 0. */
  482. Xextern IFFP IFFWriteBytes(GroupContext *, BYTE *, LONG);
  483. X              /*  context,        *data,  nBytes  */
  484. X
  485. X/* Complete the current chunk, write a pad byte if needed, and update
  486. X * GroupContext.
  487. X * If current chunk's ckSize = szNotYetKnown, this goes back and sets the
  488. X * ckSize in the file.
  489. X * CLIENT_ERROR if PutCkHdr wasn't called first, or if client hasn't
  490. X * written 'ckSize' number of bytes with IFFWriteBytes. */
  491. Xextern IFFP PutCkEnd(GroupContext *);
  492. X         /*  context  */
  493. X
  494. X#else /* not FDwAT */
  495. X
  496. Xextern IFFP OpenWIFF();
  497. Xextern IFFP StartWGroup();
  498. Xextern IFFP EndWGroup();
  499. Xextern IFFP OpenWGroup();
  500. Xextern IFFP CloseWGroup();
  501. Xextern IFFP PutCk();
  502. Xextern IFFP PutCkHdr();
  503. Xextern IFFP IFFWriteBytes();
  504. Xextern IFFP PutCkEnd();
  505. X
  506. X#endif /* not FDwAT */
  507. X
  508. X#endif IFF_H
  509. X
  510. END_OF_FILE
  511. if test 20481 -ne `wc -c <'src/iff.h'`; then
  512.     echo shar: \"'src/iff.h'\" unpacked with wrong size!
  513. fi
  514. # end of 'src/iff.h'
  515. fi
  516. if test -f 'src/lighting.c' -a "${1}" != "-c" ; then 
  517.   echo shar: Will not clobber existing file \"'src/lighting.c'\"
  518. else
  519. echo shar: Extracting \"'src/lighting.c'\" \(18901 characters\)
  520. sed "s/^X//" >'src/lighting.c' <<'END_OF_FILE'
  521. X/*****************************************************************************
  522. X*
  523. X*                                    lighting.c
  524. X*
  525. X*   from DKBTrace (c) 1990  David Buck
  526. X*
  527. X*  This module calculates lighting properties like ambient, diffuse, specular,
  528. X*  reflection, refraction, etc.
  529. X*
  530. X*
  531. X* This software is freely distributable. The source and/or object code may be
  532. X* copied or uploaded to communications services so long as this notice remains
  533. X* at the top of each file.  If any changes are made to the program, you must
  534. X* clearly indicate in the documentation and in the programs startup message
  535. X* who it was who made the changes. The documentation should also describe what
  536. X* those changes were. This software may not be included in whole or in
  537. X* part into any commercial package without the express written consent of the
  538. X* author.  It may, however, be included in other public domain or freely
  539. X* distributed software so long as the proper credit for the software is given.
  540. X*
  541. X* This software is provided as is without any guarantees or warranty. Although
  542. X* the author has attempted to find and correct any bugs in the software, he
  543. X* is not responsible for any damage caused by the use of the software.  The
  544. X* author is under no obligation to provide service, corrections, or upgrades
  545. X* to this package.
  546. X*
  547. X* Despite all the legal stuff above, if you do find bugs, I would like to hear
  548. X* about them.  Also, if you have any comments or questions, you may contact me
  549. X* at the following address:
  550. X*
  551. X*     David Buck
  552. X*     22C Sonnet Cres.
  553. X*     Nepean Ontario
  554. X*     Canada, K2H 8W7
  555. X*
  556. X*  I can also be reached on the following bulleton boards:
  557. X*
  558. X*     ATX              (613) 526-4141
  559. X*     OMX              (613) 731-3419
  560. X*     Mystic           (613) 731-0088 or (613) 731-6698
  561. X*
  562. X*  Fidonet:   1:163/109.9
  563. X*  Internet:  David_Buck@Carleton.CA
  564. X*
  565. X*  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  566. X*
  567. X*     Lattice BBS                      (708) 916-1200
  568. X*     The Information Exchange BBS     (708) 945-5575
  569. X*     Stillwaters BBS                  (708) 403-2826
  570. X*
  571. X*****************************************************************************/
  572. X
  573. X
  574. X#include "frame.h"
  575. X#include "vector.h"
  576. X#include "dkbproto.h"
  577. X
  578. Xextern int Trace_Level;
  579. Xextern FRAME Frame;
  580. Xextern unsigned long Options;
  581. Xextern int Quality;
  582. Xextern long Shadow_Ray_Tests, Shadow_Rays_Succeeded;
  583. Xextern long Reflected_Rays_Traced, Refracted_Rays_Traced;
  584. Xextern long Transmitted_Rays_Traced;
  585. X
  586. X#define Small_Tolerance 0.001
  587. X
  588. Xvoid Colour_At (Colour, Object, Intersection_Point)
  589. X   COLOUR *Colour;
  590. X   OBJECT *Object;
  591. X   VECTOR *Intersection_Point;
  592. X   {
  593. X   register DBL x, y, z;
  594. X   VECTOR Transformed_Point;
  595. X
  596. X   if (Object -> Object_Texture->Texture_Transformation) {
  597. X      MInverseTransformVector (&Transformed_Point,
  598. X                               Intersection_Point,
  599. X                   Object -> Object_Texture->Texture_Transformation);
  600. X      }
  601. X   else
  602. X      Transformed_Point = *Intersection_Point;
  603. X
  604. X   x = Transformed_Point.x;
  605. X   y = Transformed_Point.y;
  606. X   z = Transformed_Point.z;
  607. X     
  608. X   switch (Object -> Object_Texture->Texture_Number) {
  609. X      case BOZO_TEXTURE: 
  610. X           Bozo (x, y, z, Object, Colour);
  611. X           break;
  612. X
  613. X      case MARBLE_TEXTURE:
  614. X           marble (x, y, z, Object, Colour);
  615. X           break;
  616. X
  617. X      case WOOD_TEXTURE:
  618. X           wood (x, y, z, Object, Colour);
  619. X           break;
  620. X
  621. X      case CHECKER_TEXTURE:
  622. X           checker (x, y, z, Object, Colour);
  623. X           break;
  624. X
  625. X      case SPOTTED_TEXTURE:
  626. X           spotted (x, y, z, Object, Colour);
  627. X           break;
  628. X
  629. X      case AGATE_TEXTURE:
  630. X           agate (x, y, z, Object, Colour);
  631. X           break;
  632. X
  633. X      case GRANITE_TEXTURE:
  634. X           granite (x, y, z, Object, Colour);
  635. X           break;
  636. X
  637. X     case GRADIENT_TEXTURE:
  638. X           gradient (x, y, z, Object, Colour);
  639. X           break;
  640. X
  641. X      case IMAGEMAP_TEXTURE:
  642. X           texture_map (x, y, z, Object, Colour);
  643. X       break;
  644. X
  645. X      default:
  646. X           *Colour = Object -> Object_Colour;
  647. X           break;
  648. X      }
  649. X   }
  650. X
  651. X
  652. Xvoid Perturb_Normal(New_Normal, Object, Intersection_Point, Surface_Normal)
  653. X   VECTOR *New_Normal, *Intersection_Point, *Surface_Normal;
  654. X   OBJECT *Object;
  655. X   {
  656. X   VECTOR Transformed_Point;
  657. X   register DBL x, y, z;
  658. X
  659. X   if (Object -> Object_Texture->Bump_Number == NO_BUMPS) {
  660. X      *New_Normal = *Surface_Normal;
  661. X      return;
  662. X      }
  663. X
  664. X   if (Object -> Object_Texture->Texture_Transformation)
  665. X      MInverseTransformVector (&Transformed_Point,
  666. X                               Intersection_Point,
  667. X                               Object -> Object_Texture->Texture_Transformation);
  668. X   else
  669. X      Transformed_Point = *Intersection_Point;
  670. X
  671. X   x = Transformed_Point.x;
  672. X   y = Transformed_Point.y;
  673. X   z = Transformed_Point.z;
  674. X
  675. X   switch (Object -> Object_Texture->Bump_Number) {
  676. X      case NO_BUMPS: break;
  677. X
  678. X      case WAVES: waves (x, y, z, Object, New_Normal);
  679. X                  break;
  680. X
  681. X      case RIPPLES: ripples (x, y, z, Object, New_Normal);
  682. X                  break;
  683. X
  684. X      case WRINKLES: wrinkles (x, y, z, Object, New_Normal);
  685. X                  break;
  686. X
  687. X      case BUMPS: bumps (x, y, z, Object, New_Normal);
  688. X                  break;
  689. X
  690. X      case DENTS: dents (x, y, z, Object, New_Normal);
  691. X                  break;
  692. X      }
  693. X   return;
  694. X   }
  695. X
  696. Xvoid Ambient (Object, Intersection_Point, Surface_Colour, Colour)
  697. X   OBJECT *Object;
  698. X   VECTOR *Intersection_Point;
  699. X   COLOUR *Surface_Colour;
  700. X   COLOUR *Colour;
  701. X   {
  702. X   DBL t;
  703. X
  704. X   if (Object -> Object_Texture -> Object_Ambient == 0.0)
  705. X      return;
  706. X
  707. X   t = 1.0 - Surface_Colour->Alpha;
  708. X   Colour->Red += Surface_Colour->Red * t * Object->Object_Texture->Object_Ambient;
  709. X   Colour->Green += Surface_Colour->Green * t * Object->Object_Texture->Object_Ambient;
  710. X   Colour->Blue += Surface_Colour->Blue * t * Object->Object_Texture->Object_Ambient;
  711. X   return;
  712. X   }
  713. X
  714. X
  715. Xvoid Diffuse (Object, Intersection_Point, Eye, Surface_Normal, Surface_Colour, Colour)
  716. X   OBJECT *Object;
  717. X   VECTOR *Intersection_Point, *Surface_Normal;
  718. X   COLOUR *Surface_Colour;
  719. X   COLOUR *Colour;
  720. X   RAY *Eye;
  721. X   {
  722. X   DBL Cos_Angle_Of_Incidence, Halfway_Length, Normal_Length;
  723. X   DBL Intensity, RandomNumber, Light_Source_Depth;
  724. X   RAY Light_Source_Ray;
  725. X   OBJECT *Light_Source, *Blocking_Object;
  726. X   int Intersection_Found;
  727. X   INTERSECTION *Local_Intersection;
  728. X   VECTOR Halfway, REye, Local_Normal, Normal_Projection, Reflect_Direction;
  729. X   COLOUR Light_Colour, Blocking_Colour;
  730. X   PRIOQ *Local_Queue;
  731. X
  732. X   if ((Object -> Object_Texture -> Object_Diffuse == 0.0) &&
  733. X       (Object -> Object_Texture -> Object_Specular == 0.0) &&
  734. X       (Object -> Object_Texture -> Object_Phong == 0.0))
  735. X     return;
  736. X
  737. X   if (Object -> Object_Texture -> Object_Specular != 0.0)
  738. X      {
  739. X      REye.x = -Eye->Direction.x;
  740. X      REye.y = -Eye->Direction.y;
  741. X      REye.z = -Eye->Direction.z;
  742. X      }
  743. X
  744. X   Local_Queue = pq_new (128);
  745. X
  746. X   for (Light_Source = Frame.Light_Sources ; 
  747. X        Light_Source != NULL;
  748. X        Light_Source = Light_Source -> Next_Light_Source)
  749. X      {
  750. X      Intersection_Found = FALSE;  
  751. X      Light_Source_Ray.Initial = *Intersection_Point;
  752. X      Light_Source_Ray.Quadric_Constants_Cached = FALSE;
  753. X      Light_Colour = Light_Source->Object_Colour;
  754. X
  755. X      VSub (Light_Source_Ray.Direction,
  756. X           Light_Source->Object_Center,
  757. X       *Intersection_Point);
  758. X
  759. X      VLength (Light_Source_Depth, Light_Source_Ray.Direction);
  760. X
  761. X      VScale (Light_Source_Ray.Direction, Light_Source_Ray.Direction,
  762. X                1.0/Light_Source_Depth);
  763. X
  764. X    /* What objects does this ray intersect? */
  765. X      if (Quality > 3)
  766. X         for (Blocking_Object = Frame.Objects ; 
  767. X              Blocking_Object != NULL ;
  768. X              Blocking_Object = Blocking_Object -> Next_Object) {
  769. X
  770. X            Shadow_Ray_Tests++;
  771. X            if (Blocking_Object == Light_Source)
  772. X               continue;
  773. X
  774. X            for (All_Intersections (Blocking_Object, &Light_Source_Ray, Local_Queue) ;
  775. X                 (Local_Intersection = pq_get_highest(Local_Queue)) != NULL ;
  776. X                 pq_delete_highest(Local_Queue)) {
  777. X
  778. X               if ((Local_Intersection -> Depth < Light_Source_Depth-Small_Tolerance)
  779. X                    && (Local_Intersection -> Depth > Small_Tolerance))
  780. X                  {
  781. X                  Shadow_Rays_Succeeded++;
  782. X                  if (Blocking_Object->Transparency) {
  783. X                     Make_Colour(&Blocking_Colour, 0.0, 0.0, 0.0);
  784. X                     Colour_At(&Blocking_Colour, Blocking_Object, &Local_Intersection->Point);
  785. X                     Light_Colour.Red *= 
  786. X                                    Blocking_Colour.Red * Blocking_Colour.Alpha;
  787. X                     Light_Colour.Green *= 
  788. X                                    Blocking_Colour.Green * Blocking_Colour.Alpha;
  789. X                     Light_Colour.Blue *=
  790. X                                    Blocking_Colour.Blue * Blocking_Colour.Alpha;
  791. X                     }
  792. X                  else {
  793. X                     Intersection_Found = TRUE;
  794. X                     break;
  795. X                     }
  796. X                  }
  797. X               }
  798. X            if (Intersection_Found) {
  799. X               while (pq_get_highest(Local_Queue))
  800. X                  pq_delete_highest(Local_Queue);
  801. X               break;
  802. X               }
  803. X            }
  804. X
  805. X      if (!Intersection_Found)
  806. X         {
  807. X         if (Object->Object_Texture->Object_Phong)      /* Phong Specular Highlight rtn. */
  808. X        {
  809. X            VDot(Cos_Angle_Of_Incidence, Eye->Direction, *Surface_Normal);
  810. X            if (Cos_Angle_Of_Incidence < 0.0)
  811. X               {
  812. X               Local_Normal = *Surface_Normal;
  813. X               Cos_Angle_Of_Incidence = -Cos_Angle_Of_Incidence;
  814. X               }
  815. X            else
  816. X               VScale (Local_Normal, *Surface_Normal, -1.0);
  817. X
  818. X            VScale (Normal_Projection, Local_Normal, Cos_Angle_Of_Incidence);
  819. X            VScale (Normal_Projection, Normal_Projection, 2.0);
  820. X            VAdd (Reflect_Direction, Eye->Direction, Normal_Projection);
  821. X
  822. X            VDot (Cos_Angle_Of_Incidence, Reflect_Direction, Light_Source_Ray.Direction);
  823. X            VLength (Normal_Length, Light_Source_Ray.Direction);
  824. X            Cos_Angle_Of_Incidence /= Normal_Length;
  825. X
  826. X            if (Cos_Angle_Of_Incidence < 0.0)
  827. X               Cos_Angle_Of_Incidence = 0;
  828. X
  829. X            if (Object -> Object_Texture -> Object_PhongSize != 1.0)
  830. X               Intensity = pow(Cos_Angle_Of_Incidence, Object->Object_Texture->Object_PhongSize);
  831. X            else
  832. X               Intensity = Cos_Angle_Of_Incidence;
  833. X
  834. X            Intensity *= Object -> Object_Texture -> Object_Phong;
  835. X
  836. X            Colour->Red+=Intensity*(Light_Colour.Red);
  837. X            Colour->Green+=Intensity*(Light_Colour.Green);
  838. X            Colour->Blue+=Intensity*(Light_Colour.Blue);
  839. X            }
  840. X
  841. X         if (Object->Object_Texture->Object_Specular > 0.0)   /* better specular highlights */
  842. X            {
  843. X            VHalf (Halfway, REye, Light_Source_Ray.Direction);
  844. X            VLength (Normal_Length, *Surface_Normal);
  845. X            VLength (Halfway_Length, Halfway);
  846. X            VDot (Cos_Angle_Of_Incidence, Halfway, *Surface_Normal);
  847. X            Cos_Angle_Of_Incidence /= (Normal_Length * Halfway_Length);
  848. X
  849. X            if (Cos_Angle_Of_Incidence < 0.0)
  850. X               Cos_Angle_Of_Incidence = 0;
  851. X
  852. X            if (Object -> Object_Texture -> Object_Roughness != 1.0)
  853. X               Intensity = pow(Cos_Angle_Of_Incidence, 1 / Object->Object_Texture->Object_Roughness);
  854. X            else
  855. X               Intensity = Cos_Angle_Of_Incidence;
  856. X
  857. X            Intensity *= Object->Object_Texture->Object_Specular;
  858. X
  859. X            Colour->Red+=Intensity* (Light_Colour.Red);
  860. X            Colour->Green+=Intensity* (Light_Colour.Green);
  861. X            Colour->Blue+=Intensity* (Light_Colour.Blue);
  862. X            }
  863. X
  864. X         if (Object->Object_Texture->Object_Diffuse > 0.0)      /* now do normal diffuse */
  865. X            {
  866. X            VDot (Cos_Angle_Of_Incidence, *Surface_Normal, Light_Source_Ray.Direction);
  867. X            if (Cos_Angle_Of_Incidence < 0.0)
  868. X               Cos_Angle_Of_Incidence = -Cos_Angle_Of_Incidence;
  869. X    
  870. X            if (Object -> Object_Texture -> Object_Brilliance != 1.0)
  871. X               Intensity = pow(Cos_Angle_Of_Incidence, Object->Object_Texture->Object_Brilliance);
  872. X        else
  873. X               Intensity = Cos_Angle_Of_Incidence;
  874. X
  875. X            Intensity *= Object -> Object_Texture -> Object_Diffuse;
  876. X
  877. X            RandomNumber = (rand()&0x7FFF)/(DBL) 0x7FFF;
  878. X
  879. X            Intensity -= RandomNumber * Object->Object_Texture->Texture_Randomness;
  880. X
  881. X            Intensity *= 1.0 - Surface_Colour->Alpha;
  882. X        Colour->Red += Intensity * (Surface_Colour->Red) * (Light_Colour.Red);
  883. X            Colour->Green += Intensity * (Surface_Colour->Green) * (Light_Colour.Green);
  884. X            Colour->Blue += Intensity * (Surface_Colour->Blue) * (Light_Colour.Blue);
  885. X        }
  886. X         }
  887. X      }
  888. X   pq_free (Local_Queue);
  889. X   return;
  890. X   }
  891. X
  892. Xvoid Transmit (Object, Intersection_Point, Ray, Surface_Normal, Surface_Colour, Colour)
  893. X   OBJECT *Object;
  894. X   VECTOR *Intersection_Point;
  895. X   RAY *Ray;
  896. X   VECTOR *Surface_Normal;
  897. X   COLOUR *Surface_Colour;
  898. X   COLOUR *Colour;
  899. X   {
  900. X   RAY New_Ray;
  901. X   COLOUR Temp_Colour;
  902. X
  903. X   if (Surface_Colour->Alpha == 0.0)
  904. X      return;
  905. X
  906. X   New_Ray.Initial = *Intersection_Point;
  907. X   New_Ray.Direction = Ray->Direction;
  908. X
  909. X   Copy_Ray_Containers (&New_Ray, Ray);
  910. X   Trace_Level++;
  911. X   Transmitted_Rays_Traced++;
  912. X   Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  913. X   New_Ray.Quadric_Constants_Cached = FALSE;
  914. X   Trace (&New_Ray, &Temp_Colour);
  915. X   Trace_Level--;
  916. X   (Colour -> Red) += Temp_Colour.Red * Surface_Colour->Red * Surface_Colour->Alpha;
  917. X   (Colour -> Green) += Temp_Colour.Green * Surface_Colour->Green * Surface_Colour->Alpha;
  918. X   (Colour -> Blue) += Temp_Colour.Blue * Surface_Colour->Blue * Surface_Colour->Alpha;
  919. X   }
  920. X
  921. X
  922. Xvoid Reflect (Object, Intersection_Point, Ray, Surface_Normal, Colour)
  923. X   OBJECT *Object;
  924. X   VECTOR *Intersection_Point;
  925. X   RAY *Ray;
  926. X   VECTOR *Surface_Normal;
  927. X   COLOUR *Colour;
  928. X   {
  929. X   RAY New_Ray;
  930. X   COLOUR Temp_Colour;
  931. X   VECTOR Local_Normal;
  932. X   VECTOR Normal_Projection;
  933. X   register DBL Normal_Component;
  934. X
  935. X   if (Object -> Object_Texture -> Object_Reflection != 0.0)
  936. X      {
  937. X      Reflected_Rays_Traced++;
  938. X      VDot (Normal_Component, Ray -> Direction, *Surface_Normal);
  939. X      if (Normal_Component < 0.0) {
  940. X         Local_Normal = *Surface_Normal;
  941. X         Normal_Component *= -1.0;
  942. X         }
  943. X      else
  944. X         VScale (Local_Normal, *Surface_Normal, -1.0);
  945. X
  946. X      VScale (Normal_Projection, Local_Normal, Normal_Component);
  947. X      VScale (Normal_Projection, Normal_Projection, 2.0);
  948. X      VAdd (New_Ray.Direction, Ray -> Direction, Normal_Projection);
  949. X      New_Ray.Initial = *Intersection_Point;
  950. X
  951. X      Copy_Ray_Containers (&New_Ray, Ray);
  952. X      Trace_Level++;
  953. X      Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  954. X      New_Ray.Quadric_Constants_Cached = FALSE;
  955. X      Trace (&New_Ray, &Temp_Colour);
  956. X      Trace_Level--;
  957. X      (Colour -> Red) += (Temp_Colour.Red) 
  958. X                             * (Object -> Object_Texture -> Object_Reflection);
  959. X      (Colour -> Green) += (Temp_Colour.Green)
  960. X                             * (Object -> Object_Texture -> Object_Reflection);
  961. X      (Colour -> Blue) += (Temp_Colour.Blue)
  962. X                             * (Object -> Object_Texture -> Object_Reflection);
  963. X      }
  964. X   }
  965. X
  966. Xvoid Refract (Object, Intersection_Point, Ray, Surface_Normal, Colour)
  967. X   OBJECT *Object;
  968. X   VECTOR *Intersection_Point;
  969. X   RAY *Ray;
  970. X   VECTOR *Surface_Normal;
  971. X   COLOUR *Colour;
  972. X   {
  973. X   RAY New_Ray;
  974. X   COLOUR Temp_Colour;
  975. X   VECTOR Local_Normal;
  976. X   VECTOR Normal_Projection;
  977. X   register DBL Normal_Component, Temp_IOR;
  978. X
  979. X   if (Object -> Object_Texture -> Object_Refraction != 0.0)
  980. X      {
  981. X      Refracted_Rays_Traced++;
  982. X      VDot (Normal_Component, Ray -> Direction, *Surface_Normal);
  983. X      if (Normal_Component >= 0.0)
  984. X         {
  985. X         VScale (Local_Normal, *Surface_Normal, -1.0);
  986. X         }
  987. X      else
  988. X         {
  989. X         Local_Normal.x = Surface_Normal -> x;
  990. X         Local_Normal.y = Surface_Normal -> y;
  991. X         Local_Normal.z = Surface_Normal -> z;
  992. X
  993. X         Normal_Component *= -1.0;
  994. X         }
  995. X
  996. X      VScale (Normal_Projection, Local_Normal, Normal_Component);
  997. X      VAdd (Normal_Projection, Normal_Projection, Ray -> Direction);
  998. X      Copy_Ray_Containers (&New_Ray, Ray);
  999. X
  1000. X      if (Ray -> Containing_Index == -1)
  1001. X         {
  1002. X       /* The ray is entering from the atmosphere */
  1003. X         Ray_Enter (&New_Ray, Object);
  1004. X
  1005. X         VScale (Normal_Projection, Normal_Projection,
  1006. X               (Frame.Atmosphere_IOR)/(Object -> Object_Texture -> Object_Index_Of_Refraction));
  1007. X         }
  1008. X      else
  1009. X         {
  1010. X       /* The ray is currently inside an object */
  1011. X         if (New_Ray.Containing_Objects [New_Ray.Containing_Index] == Object)
  1012. X            {
  1013. X          /* The ray is leaving the current object */
  1014. X            Ray_Exit (&New_Ray);
  1015. X            if (New_Ray.Containing_Index == -1)
  1016. X             /* The ray is leaving into the atmosphere */
  1017. X               Temp_IOR = Frame.Atmosphere_IOR;
  1018. X            else
  1019. X             /* The ray is leaving into another object */
  1020. X               Temp_IOR = New_Ray.Containing_IORs [New_Ray.Containing_Index];
  1021. X
  1022. X            VScale (Normal_Projection, Normal_Projection,
  1023. X               (Object -> Object_Texture -> Object_Index_Of_Refraction) / Temp_IOR);
  1024. X            }
  1025. X         else
  1026. X            {
  1027. X            /* The ray is entering a new object */
  1028. X            Temp_IOR = New_Ray.Containing_IORs [New_Ray.Containing_Index];
  1029. X            Ray_Enter (&New_Ray, Object);
  1030. X
  1031. X            VScale (Normal_Projection, Normal_Projection,
  1032. X                 Temp_IOR/(Object -> Object_Texture -> Object_Index_Of_Refraction));
  1033. X
  1034. X            }
  1035. X         }
  1036. X
  1037. X      VScale (Local_Normal, Local_Normal, -1.0);
  1038. X      VAdd (New_Ray.Direction, Local_Normal, Normal_Projection);
  1039. X      VNormalize (New_Ray.Direction, New_Ray.Direction);
  1040. X      New_Ray.Initial = *Intersection_Point;
  1041. X      Trace_Level++;
  1042. X      Make_Colour (&Temp_Colour, 0.0, 0.0, 0.0);
  1043. X      New_Ray.Quadric_Constants_Cached = FALSE;
  1044. X      Trace (&New_Ray, &Temp_Colour);
  1045. X      Trace_Level--;
  1046. X      (Colour -> Red) += (Temp_Colour.Red)
  1047. X                        * (Object -> Object_Texture -> Object_Refraction);
  1048. X      (Colour -> Green) += (Temp_Colour.Green)
  1049. X                        * (Object -> Object_Texture -> Object_Refraction);
  1050. X      (Colour -> Blue) += (Temp_Colour.Blue)
  1051. X                        * (Object -> Object_Texture -> Object_Refraction);
  1052. X      }  
  1053. X   }
  1054. X
  1055. Xvoid Fog (Distance, Fog_Colour, Fog_Distance, Colour)
  1056. X   DBL Distance, Fog_Distance;
  1057. X   COLOUR *Fog_Colour, *Colour;
  1058. X   {
  1059. X   DBL Fog_Factor, Fog_Factor_Inverse;
  1060. X
  1061. X   Fog_Factor = exp(-1.0 * Distance/Fog_Distance);
  1062. X   Fog_Factor_Inverse = 1.0 - Fog_Factor;
  1063. X   Colour->Red = Colour->Red*Fog_Factor + Fog_Colour->Red*Fog_Factor_Inverse;
  1064. X   Colour->Green = Colour->Green*Fog_Factor + Fog_Colour->Green*Fog_Factor_Inverse;
  1065. X   Colour->Blue = Colour->Blue*Fog_Factor + Fog_Colour->Blue*Fog_Factor_Inverse;
  1066. X   }
  1067. END_OF_FILE
  1068. if test 18901 -ne `wc -c <'src/lighting.c'`; then
  1069.     echo shar: \"'src/lighting.c'\" unpacked with wrong size!
  1070. fi
  1071. # end of 'src/lighting.c'
  1072. fi
  1073. echo shar: End of archive 7 \(of 10\).
  1074. cp /dev/null ark7isdone
  1075. MISSING=""
  1076. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  1077.     if test ! -f ark${I}isdone ; then
  1078.     MISSING="${MISSING} ${I}"
  1079.     fi
  1080. done
  1081. if test "${MISSING}" = "" ; then
  1082.     echo You have unpacked all 10 archives.
  1083.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1084. else
  1085.     echo You still need to unpack the following archives:
  1086.     echo "        " ${MISSING}
  1087. fi
  1088. ##  End of shell archive.
  1089. exit 0
  1090. -- 
  1091. Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
  1092. Mail comments to the moderator at <amiga-request@uunet.uu.net>.
  1093. Post requests for sources, and general discussion to comp.sys.amiga.
  1094.